package gao.xiaolei.service;

import gao.xiaolei.dao.ReqDesignRunViewDao;
import gao.xiaolei.dao.TestBugDao;
import gao.xiaolei.dao.TestReqAnalysisDao;
import gao.xiaolei.dao.TestRequirementDao;
import gao.xiaolei.dto.AnalysisOutDto;
import gao.xiaolei.entity.ReqDesignRunView;
import gao.xiaolei.entity.TestReqAnalysis;
import gao.xiaolei.entity.TestRequirement;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;

@Service("AnalysisService")
public class AnalysisService {

    @Resource(name = "ReqDesignRunViewDao")
    private ReqDesignRunViewDao reqDesignRunViewDao;

    @Resource(name = "TestReqAnalysisDao")
    private TestReqAnalysisDao testReqAnalysisDao;

    @Resource(name = "TestRequirementDao")
    private TestRequirementDao testRequirementDao;

    @Resource(name = "TestBugDao")
    private TestBugDao testBugDao;

    @Transactional(readOnly = true)
    public AnalysisOutDto getAnalysisByParentId(String projectId, String parentId) {
        List<TestReqAnalysis> analyses = testReqAnalysisDao.findAllByParentIdAndProjectId(parentId, projectId);
        for (int i = 0, length = analyses.size(); i < length; i++) {//获取测试需求的名字
            analyses.get(i).setName(testRequirementDao.getTitle(analyses.get(i).getId()));
        }
        AnalysisOutDto outDto = new AnalysisOutDto();
        if ("root".equals(parentId)) {//如果是拿最顶端节点就要去算覆盖率
            int sum = 0, noCoverCount = 0;
            for (int i = 0, length = analyses.size(); i < length; i++) {
                sum = sum + analyses.get(i).getNotCoveredCount() + analyses.get(i).getNotCompletedCount() + analyses.get(i).getFailedCount() + analyses.get(i).getPassCount();
                noCoverCount = noCoverCount + analyses.get(i).getNotCoveredCount();
            }
            float coverPercent = sum == 0 ? 0 : ((float) (sum - noCoverCount)) / sum * 100;//防止分母为0的情况
            outDto.setCoverPercent(coverPercent);
        }
        outDto.setReqAnalyses(analyses);
        return outDto;
    }

   // @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    @Transactional
    //对某个测试项目进行分析并持久化
    public void doAnalysis(String projectId) {
        testReqAnalysisDao.deleteAllByProjectId(projectId);//先删掉该项目的分析再去重新生成，不然会有遗漏
        recurrenceAnalysis("root", projectId);
    }

    @Transactional(readOnly = true)
    //获取某个项目的测试需求覆盖率
    public float getProjectTrqCoverPercent(String projectId) {
        List<TestReqAnalysis> analyses = testReqAnalysisDao.findAllByParentIdAndProjectId("root", projectId);
        int sum = 0, noCoverCount = 0;
        for (int i = 0, length = analyses.size(); i < length; i++) {
            sum = sum + analyses.get(i).getNotCoveredCount() + analyses.get(i).getNotCompletedCount() + analyses.get(i).getFailedCount() + analyses.get(i).getPassCount();
            noCoverCount = noCoverCount + analyses.get(i).getNotCoveredCount();
        }
        return sum == 0 ? 0 : ((float) (sum - noCoverCount)) / sum * 100;//防止分母为0的情况
    }


    //递归需求树，分析每个叶子需求的情况
    private NoteCount recurrenceAnalysis(String parentId, String projectId) {
        List<TestRequirement> childrenReq = "root".equals(parentId) ? testRequirementDao.findByProjectAndStatusAndParentId(projectId, 3, parentId) : testRequirementDao.findByStatusAndParentId(3, parentId);
        NoteCount noteCount = new NoteCount();
        for (int i = 0, length = childrenReq.size(); i < length; i++) {
            if (childrenReq.get(i).getLeaf() == 1) {//如果是叶子节点的话
                TestReqAnalysis analysis = new TestReqAnalysis(childrenReq.get(i).getId(), projectId, childrenReq.get(i).getLeaf(), childrenReq.get(i).getParentId());
                if (!reqDesignRunViewDao.existsAllByTrqIdAndDesignIdIsNotNull(childrenReq.get(i).getId())) {//如果不存在说明此需求没有被覆盖到
                    noteCount.setNotCoveredCount(noteCount.getNotCoveredCount() + 1);//未覆盖数+1
                    analysis.setNotCoveredCount(1);//用于持久化的分析实体
                } else {//如果覆盖了就要继续看执行结果
                    ReqDesignRunView view = reqDesignRunViewDao.findTopByTrqIdAndRunLogStatusIsNotNullOrderByRunLogDateDesc(childrenReq.get(i).getId());
                    if (view == null) { //如果查出来是null说明该需求没有对应的测试执行纪录
                        noteCount.setNotCompletedCount(noteCount.getNotCompletedCount() + 1);//未完成数+1
                        analysis.setNotCompletedCount(1);//用于持久化的分析实体
                    } else {//不然就要看一下执行结果到底是什么
                        if (view.getRunLogStatus() == -1) {
                            noteCount.setNotCompletedCount(noteCount.getNotCompletedCount() + 1);
                            analysis.setNotCompletedCount(1);//用于持久化的分析实体
                        } else if (view.getRunLogStatus() == 0) {
                            noteCount.setFailedCount(noteCount.getFailedCount() + 1);
                            analysis.setFailedCount(1);//用于持久化的分析实体
                        } else {
                            noteCount.setPassCount(noteCount.getPassCount() + 1);
                            analysis.setPassCount(1);//用于持久化的分析实体
                        }
                    }
                }
                int bugCount=testBugDao.countAllByToTrq(childrenReq.get(i).getId());
                analysis.setBugCount(bugCount);
                noteCount.setBugCount(bugCount);
                testReqAnalysisDao.save(analysis);//将该需求的统计数据持久化到分析表中,叶子节点直接持久化自己的数据即可
            } else {//如果不是叶子节点就继续递归,并将子节点的统计数据汇总到noteCount
                NoteCount childrenNoteCount = recurrenceAnalysis(childrenReq.get(i).getId(), projectId);
                noteCount.setNotCoveredCount(noteCount.getNotCoveredCount() + childrenNoteCount.getNotCoveredCount());
                noteCount.setNotCompletedCount(noteCount.getNotCompletedCount() + childrenNoteCount.getNotCompletedCount());
                noteCount.setFailedCount(noteCount.getFailedCount() + childrenNoteCount.getFailedCount());
                noteCount.setPassCount(noteCount.getPassCount() + childrenNoteCount.getPassCount());
                noteCount.setBugCount(noteCount.getBugCount() + childrenNoteCount.getBugCount());
                //不是叶子节点就持久化儿子传上来的统计数据数据
                testReqAnalysisDao.save(new TestReqAnalysis(childrenReq.get(i).getId(), projectId, childrenReq.get(i).getLeaf(), childrenReq.get(i).getParentId(), childrenNoteCount.getNotCoveredCount(), childrenNoteCount.getNotCompletedCount(), childrenNoteCount.getFailedCount(), childrenNoteCount.getPassCount(), childrenNoteCount.getBugCount()));
            }
        }
        return noteCount;
    }


    private class NoteCount {
        private int notCoveredCount;//未覆盖的叶子节点数量

        private int notCompletedCount;//未完成的叶子节点数量

        private int failedCount;//执行失败的叶子节点数量

        private int passCount;//执行成功的叶子节点数量

        private int bugCount;//叶子节点的bug数量

        public NoteCount() {
        }

        public int getNotCoveredCount() {
            return notCoveredCount;
        }

        public void setNotCoveredCount(int notCoveredCount) {
            this.notCoveredCount = notCoveredCount;
        }

        public int getNotCompletedCount() {
            return notCompletedCount;
        }

        public void setNotCompletedCount(int notCompletedCount) {
            this.notCompletedCount = notCompletedCount;
        }

        public int getFailedCount() {
            return failedCount;
        }

        public void setFailedCount(int failedCount) {
            this.failedCount = failedCount;
        }

        public int getPassCount() {
            return passCount;
        }

        public void setPassCount(int passCount) {
            this.passCount = passCount;
        }

        public int getBugCount() {
            return bugCount;
        }

        public void setBugCount(int bugCount) {
            this.bugCount = bugCount;
        }
    }
}
